﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.IO.Ports;
using System.Management;
using System.Windows.Threading;
using System.Threading;
using System.Windows.Forms.DataVisualization.Charting;

namespace DebugPorgram
{
    public partial class Form : System.Windows.Forms.Form
    {
        public SerialStruct Serial;
        public EquipmentStateStruct EquipmentState;
        public DispatcherTimer dispatcherTimer = new DispatcherTimer();
        public DispatcherTimer displayMsgTimer = new DispatcherTimer();
        public DispatcherTimer powerSetTimer = new DispatcherTimer();

        public Form()
        {
            Serial.port = new SerialPort();
            Serial.name = SerialPort.GetPortNames();
            Serial.data = new byte[1024];

            EquipmentState.PA1 = new string[2];
            EquipmentState.PA2 = new string[2];
            EquipmentState.MaxTemp = new float[9];
            EquipmentState.FwdPower = new float[9];
            EquipmentState.RevPower = new float[9];
            EquipmentState.lastFwdPower = new int[9];
            EquipmentState.lastRevPower = new int[9];

            InitializeComponent();

            ManagementEventWatcher watcher = new ManagementEventWatcher("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2 or EventType = 3");
            watcher.EventArrived += SerialDeviceChange_EventArrived;
            watcher.Start();

            dispatcherTimer.Tick += DispatcherTimer_Tick;
            dispatcherTimer.Interval = new TimeSpan(0, 0, 1);

            displayMsgTimer.Tick += DisplayMsgTimer_Tick;
            displayMsgTimer.Interval = new TimeSpan(0, 0, 2);

            powerSetTimer.Tick += PowerSetTimer_Tick;
            powerSetTimer.Interval = TimeSpan.FromTicks((TimeSpan.TicksPerSecond/1000)*300);

            Serial.searchPort = SerialSearch.Text;
        }

        private void PowerSetTimer_Tick(object sender, EventArgs e)
        {
            Serial.data[1] = 0x09;
            Serial.data[2] = (byte)((UInt16)PowerTrackBar.Value >> 8);
            Serial.data[3] = (byte)PowerTrackBar.Value;
            Serial_Write(4);
            powerSetTimer.Stop();
        }

        private void DisplayMsgTimer_Tick(object sender, EventArgs e)
        {
            DisplayMsg.Text = "";
            displayMsgTimer.Stop();
        }

        private void DispatcherTimer_Tick(object sender, EventArgs e)
        {
            Serial.data[1] = 0x06;
            Serial_Write(2);
        }

        private void Serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int count;
            do
            {
                count = Serial.port.BytesToRead;
                Thread.Sleep(5);
            } while (count != Serial.port.BytesToRead);

            String str = Serial.port.ReadExisting();
            MatchCollection match;

            this.Invoke((MethodInvoker)delegate
            {
                if (DebugSwitch.Text == "调试模式：OFF")
                {
                    if (str.Contains("Equipment"))
                    {
                        try
                        {
                            if (str.Contains("PD: 0"))  // 获取PD状态
                            {
                                EquipmentState.PD = false;
                                PD_Switch.ForeColor = SystemColors.WindowText;
                                EntiretySwitch.ForeColor = SystemColors.WindowText;
                            }
                            else
                            {
                                EquipmentState.PD = true;
                                PD_Switch.ForeColor = SystemColors.Highlight;
                                EntiretySwitch.ForeColor = SystemColors.Highlight;
                            }
                            match = Regex.Matches(str, "(?<=I: ).*?(?=A)");   // 匹配电流
                            EquipmentState.PA1[0] = match[0].ToString();
                            EquipmentState.PA2[0] = match[1].ToString();

                            match = Regex.Matches(str, "(?<=T: ).*?(?=C)");   // 匹配温度
                            EquipmentState.PA1[1] = match[0].ToString();
                            EquipmentState.PA2[1] = match[1].ToString();

                            DisplayMsg.Text = "      PA1       PA2\r\n";
                            DisplayMsg.Text += String.Format("电流：{0,-5} A   {1,-5} A\r\n", EquipmentState.PA1[0], EquipmentState.PA2[0]);
                            DisplayMsg.Text += String.Format("温度：{0,-5} ℃  {1,-5} ℃\r\n", EquipmentState.PA1[1], EquipmentState.PA2[1]);

                            match = Regex.Matches(str, "(?<=P: ).*?(?=W)");    // 匹配功率

                            EquipmentState.fwd_p = match[0].ToString();
                            EquipmentState.rev_p = match[1].ToString();

                            DisplayMsg.Text += String.Format("\r\n正向：{0,-7}W\r\n反向：{1,-7}W", EquipmentState.fwd_p, EquipmentState.rev_p);

                            match = Regex.Matches(str, @"(?<=\|).*?(?=\|)");    // 匹配刀片最高温度和正反向功率
                            for (int i = 0; i < match.Count; i++)
                            {
                                if (i < 9)
                                {
                                    if (EquipmentState.MaxTemp[i] < float.Parse(match[i].ToString()))
                                        EquipmentState.MaxTemp[i] = float.Parse(match[i].ToString());
                                }
                                else if (i < 18)
                                {
                                    EquipmentState.FwdPower[i - 9] = float.Parse(match[i].ToString());
                                }
                                else
                                {
                                    EquipmentState.RevPower[i - 18] = float.Parse(match[i].ToString());
                                }
                            }

                            if (DebugSwitch.Text == "调试模式：OFF")
                            {
                                PowerChart.Series[0].Points.DataBindY(EquipmentState.FwdPower);
                                PowerChart.Series[1].Points.DataBindY(EquipmentState.RevPower);
                                PowerChart.DataManipulator.InsertEmptyPoints(10, IntervalType.Number, PowerChart.Series[0]);
                                PowerChart.DataManipulator.InsertEmptyPoints(10, IntervalType.Number, PowerChart.Series[1]);
                                TempLabel.Text = "最高温度(℃)\r\n";
                                foreach (var item in EquipmentState.MaxTemp)
                                {
                                    TempLabel.Text += String.Format(" {0, -5} ", item);
                                }
                            }
                            if (隐藏调试信息ToolStripMenuItem.Checked)
                                str = "";
                        }
                        catch (Exception ex)
                        {
                            DisplayMsg.Text = String.Format("方法:{0}\r\n\r\n信息:{1}", ex.TargetSite.ToString(), ex.Message);
                        }
                    }
                }
                SerialData.AppendText(str.Replace("\n", "\r\n"));
            });
        }

        private void SerialDeviceChange_EventArrived(object sender, EventArrivedEventArgs e)
        {
            int eventType = int.Parse(e.NewEvent.GetPropertyValue("EventType").ToString());

            if (eventType == 2)  // 插入事件
            {
                if (Serial.port == null)
                    Serial.port = new SerialPort();
                if (!Serial.port.IsOpen)
                {
                    this.Invoke((MethodInvoker)delegate
                    {
                        SerialPortRefresh();
                    });
                }
            }
            else if (eventType == 3) // 拔出事件
            {
                Serial.name = SerialPort.GetPortNames();

                if (!Serial.name.ToList().Contains(Serial.nowPort))
                {
                    this.Invoke((MethodInvoker)delegate
                    {
                        SerialClose();
                        SerialPortRefresh();
                    });
                }
            }
        }
        /// <summary>
        /// 串行端口刷新
        /// </summary>
        public void SerialPortRefresh()
        {
            int index = 0;
            bool find = false;

            List<string> PortList = new List<string>();
            ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PnPEntity WHERE Caption LIKE '%(COM%)'");
            ManagementObjectCollection collection = searcher.Get();
            foreach (ManagementObject obj in collection.Cast<ManagementObject>())
            {
                if (obj["Name"] != null && obj["Name"].ToString().Contains("COM"))
                {
                    PortList.Add(obj["Name"].ToString());
                    if (!obj["Name"].ToString().Contains(Serial.searchPort) && !find)
                        index++;
                    else
                        find = true;
                }
            }
            Serial.name = SerialPort.GetPortNames();
            SerialPortName.DataSource = PortList;
            if (find)
                SerialPortName.SelectedIndex = index;
            if (SerialPortName.Items.Count == 0)
            {
                SerialPortName.Text = "端口号";
            }
        }

        public byte ADD8_Calculation(byte[] array, int length)
        {
            byte add = 0;
            for (int i = 0; i < length; i++)
            {
                add += array[i];
            }
            return add;
        }

        public void Serial_Write(int length)
        {
            if (Serial.port.IsOpen)
            {
                Serial.data[length] = ADD8_Calculation(Serial.data, length);
                try
                {
                    Serial.port.Write(Serial.data, 0, length + 1);
                }
                catch (Exception ex)
                {
                    //MessageBox.Show("请打开串口", "提示信息");
                    DisplayMsg.Text = ex.Message;
                }
            }
        }
        /// <summary>
        /// 打开串口
        /// </summary>
        private void SerialOpen()
        {
            if (!Serial.port.IsOpen)
            {
                try
                {
                    Serial.port.Open();
                    Serial.nowPort = Serial.port.PortName;

                    SerialPortName.Enabled = false;
                    BaudRate.Enabled = false;

                    SerialSwitch.Text = "关闭串口";
                }
                catch (Exception ex)
                {
                    //MessageBox.Show("请设置端口号", "提示信息");
                    DisplayMsg.Text = ex.Message;
                }
            }
        }
        /// <summary>
        /// 关闭串口
        /// </summary>
        private void SerialClose()
        {
            SerialSwitch.Text = "打开串口";

            if (PD_Switch.Text == "关闭PD")
                this.PD_Switch_Click(null, null);
            if (DebugSwitch.Text == "调试模式：OFF")
                this.DebugSwitch_Click(null, null);

            dispatcherTimer.Stop();

            SerialPortName.Enabled = true;
            BaudRate.Enabled = true;

            if (Serial.port.IsOpen)
            {
                try
                {
                    Serial.port.Close();
                }
                catch
                {
                    Serial.port.Dispose();
                }
            }
        }

        private void SerialSwitch_Click(object sender, EventArgs e)
        {
            if (SerialSwitch.Text == "打开串口")
            {
                SerialOpen();
            }
            else if (SerialSwitch.Text == "关闭串口")
            {
                SerialClose();
            }
        }
        /// <summary>
        /// 设置波特率
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BaudRate_SelectedIndexChanged(object sender, EventArgs e)
        {
            Serial.port.BaudRate = int.Parse(BaudRate.Items[BaudRate.SelectedIndex].ToString());
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            SerialPortRefresh();
            BaudRate.SelectedIndex = 1;

            Serial.port.Encoding = Encoding.UTF8;
            Serial.port.ReadBufferSize = 1024;
            Serial.port.WriteBufferSize = 1024;
            Serial.port.ReadTimeout = 1000;
            Serial.port.WriteTimeout = 1000;
            Serial.port.Parity = Parity.None;
            Serial.port.StopBits = StopBits.One;
            Serial.port.Handshake = Handshake.None;
            Serial.port.DataBits = 8;
            Serial.port.DataReceived += Serial_DataReceived;

            Serial.data[0] = 0x66;
        }

        /// <summary>
        /// 设置驱动电压
        /// </summary>
        /// <param name="value"></param>
        private void Set_DriveVoltage(int value)
        {
            Serial.data[1] = 0x02;
            if (PD_Switch.Text == "关闭PD")
                Serial.data[2] = (byte)value;
            else
                Serial.data[2] = 0x00;
            Serial_Write(3);
        }
        /// <summary>
        /// 设置COM口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SerialPortName_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!Serial.port.IsOpen)
            {
                Serial.port.PortName = Regex.Match(SerialPortName.SelectedItem.ToString(), @"((COM\d+))").ToString();
            }
        }

        private void DriveVoltage_Scroll(object sender, EventArgs e)
        {
            DisplayVoltage.Text = ((float)DriveVoltage.Value / 10).ToString();
            Set_DriveVoltage(DriveVoltage.Value);
        }
        private void DisplayVoltage_Click(object sender, EventArgs e)
        {
            if (DriveVoltage.Value <= 25)
                DriveVoltage.Value += 5;
            else DriveVoltage.Value = 30;
            DisplayVoltage.Text = ((float)DriveVoltage.Value / 10).ToString();
            Set_DriveVoltage(DriveVoltage.Value);
        }

        private void PD_Switch_Click(object sender, EventArgs e)
        {
            DisplayVoltage.Text = "0";
            DriveVoltage.Value = 0;

            if (!Serial.port.IsOpen)
            {
                DisplayMsg.Text = "请打开串口";
                return;
            }

            Set_DriveVoltage(DriveVoltage.Value);

            Thread.Sleep(100);

            Serial.data[1] = 0x01;
            if (PD_Switch.Text == "打开PD")
            {
                PD_Switch.Text = "关闭PD";
                Serial.data[2] = 0x01;
            }
            else
            {
                PD_Switch.Text = "打开PD";
                Serial.data[2] = 0x00;
            }
            Serial_Write(3);
        }
        /// <summary>
        /// 调试模式
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DebugSwitch_Click(object sender, EventArgs e)
        {
            if (!Serial.port.IsOpen)
            {
                DisplayMsg.Text = "请打开串口";
                return;
            }
            Serial.data[1] = 0x0a;
            if (DebugSwitch.Text == "调试模式：ON")  // 开启调试模式
            {
                DebugSwitch.Text = "调试模式：OFF";
                Serial.data[2] = 0x01;
                dispatcherTimer.Start();
            }
            else // 关闭调试模式
            {
                DebugSwitch.Text = "调试模式：ON";
                Serial.data[2] = 0x00;
                dispatcherTimer.Stop();
                displayMsgTimer.Start();
            }
            Serial_Write(3);
        }

        private void SerialSearch_TextChanged(object sender, EventArgs e)
        {
            Serial.searchPort = SerialSearch.Text;
        }
        private void 刷新ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SerialPortRefresh();
        }
        private void 清空ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SerialData.Clear();
        }

        private void DisplayMsg_TextChanged(object sender, EventArgs e)
        {
            if (DebugSwitch.Text == "调试模式：ON")
                displayMsgTimer.Start();
        }

        private void GB2312ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (ToolStripMenuItem item in 编码ToolStripMenuItem.DropDownItems)
            {
                item.Checked = false;
            }
            gB2312ToolStripMenuItem.Checked = true;
            Serial.port.Encoding = Encoding.GetEncoding("GB2312");
        }

        private void ASCIIToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (ToolStripMenuItem item in 编码ToolStripMenuItem.DropDownItems)
            {
                item.Checked = false;
            }
            aSCIIToolStripMenuItem.Checked = true;
            Serial.port.Encoding = Encoding.GetEncoding("ASCII");
        }

        private void UTF8ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (ToolStripMenuItem item in 编码ToolStripMenuItem.DropDownItems)
            {
                item.Checked = false;
            }
            uTF8ToolStripMenuItem.Checked = true;
            Serial.port.Encoding = Encoding.GetEncoding("UTF-8");
        }

        private void 置顶ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.TopMost = 置顶ToolStripMenuItem.Checked;
        }

        private void 更新ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start("https://gitee.com/sword_holder/debugging-assistant/tree/master/DebugProgram/bin/Debug");
        }

        private void Re_record_Click(object sender, EventArgs e)
        {
            Array.Clear(EquipmentState.MaxTemp, 0, EquipmentState.MaxTemp.Length);
        }

        private void PowerTrackBar_Scroll(object sender, EventArgs e)
        {
            DisplayPower.Value = PowerTrackBar.Value;

            powerSetTimer.Stop();
            powerSetTimer.Start();
        }

        private void DisplayPower_ValueChanged(object sender, EventArgs e)
        {
            PowerTrackBar.Value = ((int)DisplayPower.Value);

            powerSetTimer.Stop();
            powerSetTimer.Start();
        }

        private void EntiretySwitch_Click(object sender, EventArgs e)
        {
            if (!Serial.port.IsOpen)
            {
                DisplayMsg.Text = "请打开串口";
                return;
            }
            Serial.data[1] = 0x08;
            if (EntiretySwitch.Text == "开机")
            {
                EntiretySwitch.Text = "关机";
                Serial.data[2] = 0x01;
            }
            else
            {
                EntiretySwitch.Text = "开机";
                Serial.data[2] = 0x00;
            }
            Serial_Write(3);
        }
    }
}
